package cn.gson.financial.controller;

import cn.gson.financial.annotation.IgnoresLogin;
import cn.gson.financial.annotation.TokenValid;
import cn.gson.financial.base.BaseController;
import cn.gson.financial.kernel.controller.JsonResult;
import cn.gson.financial.kernel.model.entity.AccountSets;
import cn.gson.financial.kernel.model.entity.Currency;
import cn.gson.financial.kernel.model.entity.Subject;
import cn.gson.financial.kernel.model.entity.VoucherDetails;
import cn.gson.financial.kernel.model.mapper.AccountSetsMapper;
import cn.gson.financial.kernel.model.mapper.VoucherDetailsMapper;
import cn.gson.financial.kernel.model.vo.*;
import cn.gson.financial.kernel.service.SubjectService;
import cn.gson.financial.kernel.service.VoucherService;
import cn.gson.financial.kernel.utils.BaseUtil;
import cn.gson.financial.kernel.utils.DateUtil;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;


@RestController
@RequestMapping("/accountBook")
public class AccountBookController extends BaseController {

    @Autowired
    private SubjectService service;
    @Autowired
    private VoucherService voucherService;
    @Autowired
    private VoucherDetailsMapper voucherDetailsMapper;
    @Autowired
    private AccountSetsMapper accountSetsMapper;

    @RequestMapping("list")
    public JsonResult accountBookList(Date accountDate) {
        List<Subject> data = service.accountBookList(accountDate, this.accountSetsId, false);
        List<SubjectVo> collect = data.stream().map(subject -> {
            SubjectVo subjectVo = new SubjectVo();
            BeanUtils.copyProperties(subject, subjectVo);
            return subjectVo;
        }).collect(Collectors.toList());
        return JsonResult.successful(collect);
    }

    @IgnoresLogin
    @PostMapping("list1")
    public JsonResult accountBookList1(@RequestBody SubjectSelectVo vo) {
        List<Subject> data = service.accountBookList1(vo, this.accountSetsId, false);
        List<SubjectVo> collect = data.stream().map(subject -> {
            SubjectVo subjectVo = new SubjectVo();
            BeanUtils.copyProperties(subject, subjectVo);
            return subjectVo;
        }).collect(Collectors.toList());
        return JsonResult.successful(collect);
    }
    /**
     * @description:帐铺币别筛选
     * @author: 龙泽霖
     * @date:  15:30
     * @param:
     * @return:
     **/
    @GetMapping("currencyList")
    public JsonResult accountBookCurrencyList() {
        return JsonResult.successful(service.accountBookCurrencyList(this.accountSetsId));
    }
    /**
     * 科目余额表
     *
     *
     * @param accountDate
     * @return
     */
    @RequestMapping("subjectBalance")
    public JsonResult subjectBalance(Date accountDate, Boolean showNumPrice) {
        List data = service.subjectBalance(accountDate, this.accountSetsId, showNumPrice);
        return JsonResult.successful(data);
    }


    /**
     * 科目余额表 改 动态查询
     *
     * @param
     * @return
     */
    @IgnoresLogin
    @RequestMapping("/subjectBalanceByParam")
    public JsonResult subjectBalanceByParam(String startTime, String endTime, String startSubject, String endSubject, Integer startLevel, Integer endLevel, Boolean showNumPrice, boolean isOpen,Integer currencyId) {
        List<BalanceVo> data = service.subjectBalanceByParam(startTime, endTime, startSubject, endSubject, startLevel, endLevel, this.accountSetsId, showNumPrice, isOpen,currencyId);
        List<BalanceVo> remove = new ArrayList<>();
        data.forEach(balanceVo ->{
                    if(balanceVo.getIsAuxiliary() != null && balanceVo.getIsAuxiliary() == 1){
                        remove.add(balanceVo);
                    }
                });
        data.removeAll(remove);

        return JsonResult.successful(data);
    }



    /**
     * 科目汇总
     *
     * @param accountDate
     * @return
     */
    @RequestMapping("subjectSummary")
    public JsonResult subjectSummary(Date startTime,Date endTime, Boolean showNumPrice, Integer currencyId) {
        List data = service.subjectSummary(startTime,endTime, this.accountSetsId, showNumPrice, currencyId);
        return JsonResult.successful(data);
    }

    /**
     * 明细账
     *
     * @param subjectId
     * @param accountDate
     * @param subjectCode
     * @return
     */
    @IgnoresLogin
    @GetMapping("details")
    public JsonResult accountBookDetails(Integer subjectId, Date accountDate, String subjectCode, Boolean showNumPrice) {
        System.out.println(subjectId +subjectCode +showNumPrice+accountDate) ;
        List data = this.voucherService.accountBookDetails(this.accountSetsId, subjectId, accountDate, subjectCode, showNumPrice);
        return JsonResult.successful(data);
    }

    @IgnoresLogin
    @PostMapping("/supdetails")
    public JsonResult supAccountBookDetails(@RequestBody AccountBookVo vo) {
        System.out.println(vo);
            List data1 = this.voucherService.supAccountBookDetails(vo,this.accountSetsId,vo.getSubjectId(),vo.getTimeList(),vo.getSubjectCode(),vo.getShowNumPrice(),vo.getCurrencyId());
        return JsonResult.successful(data1);
    }

    /**
     * 总账
     *
     * @param accountDate
     * @return
     */
    @IgnoresLogin
    @GetMapping("generalLedger")
    public JsonResult generalLedger(Date accountDate, Boolean showNumPrice) {
        List<Map<String, Object>> data = this.voucherService.accountGeneralLedger(this.accountSetsId, accountDate, showNumPrice);
        return JsonResult.successful(data);
    }

    /**
     * 总账 点击勾选数量核算调用的接口
     */
    @IgnoresLogin
    @GetMapping("generalLedgerByParamNum")
    public JsonResult generalLedgerByParamNum(String startTime, String endTime, String startSubject, String endSubject, Integer startLevel, Integer endLevel, Integer currencyId) {
        List<AccountBookNumVo>  data = this.voucherService.generalLedgerByParamNum(this.accountSetsId,startTime,endTime, startSubject, endSubject, startLevel, endLevel,currencyId);
        return JsonResult.successful(data);
    }

    /**
     * 总账动态查询 ywh重构
     */
    @IgnoresLogin
    @GetMapping("generalLedgerByParam")
    public JsonResult generalLedgerByParamNew(String startTime, String endTime, String startSubject, String endSubject, Integer startLevel, Integer endLevel, boolean showNumPrice,Integer currencyId) {
        List<Map<String, Object>>  data = this.voucherService.generalLedgerByParamNew(this.accountSetsId,startTime,endTime, startSubject, endSubject, startLevel, endLevel,currencyId,showNumPrice);
        if (data == null){
            return JsonResult.successful();
        }
        List<Map<String, Object>> mapsList = new ArrayList<>();
        List<Map<String, Object>> mapsSet = new ArrayList<>();
        for (Map<String, Object> datum : data) {
            mapsList.add(datum);
            mapsSet.add(datum);
        }
        List<Map<String, Object>> resulMaps = new ArrayList<>();
        for(int i = 0; i < mapsList.size(); i++){
            Subject listSub = (Subject) mapsList.get(i).get("subject");
            for(int j = 0; j < mapsSet.size(); j++){
                Subject setSub = (Subject) mapsSet.get(j).get("subject");
                if(listSub.getCode().equals(setSub.getCode())){
                    resulMaps.add(mapsSet.get(j));
                }
            }
        }
        Iterator<Map<String, Object>> iterator = resulMaps.iterator();
        while (iterator.hasNext()) {
            Map<String, Object> item = iterator.next();
            if (resulMaps.indexOf(item) != resulMaps.lastIndexOf(item)) {
                iterator.remove();
            }
        }

        resulMaps.forEach(System.out::println);
        //排序
        List<Map<String, Object>> orderByMaps = new ArrayList<>();
        List<String> codeList = new ArrayList<>();
        for (Map<String, Object> resulMap : resulMaps) {
            Subject subject = (Subject) resulMap.get("subject");
            codeList.add(subject.getCode());
        }
        List<String> collect = codeList.stream().distinct().collect(Collectors.toList());
        Collections.sort(collect);
        for (String code : collect) {
            for (Map<String, Object> resulMap : resulMaps) {
                Subject subject = (Subject) resulMap.get("subject");
                if (subject.getCode().equals(code)){
                    List<VoucherDetailVo> summary = (List<VoucherDetailVo>) resulMap.get("summary");
                    Map<String, Object> item = new HashMap<>(2);
                    item.put("subject", subject);
                    item.put("summary", summary);
                    orderByMaps.add(item);
                }
            }
        }
        return JsonResult.successful(orderByMaps);
    }

    /**
     * 总账动态查询
     *
     * @param
     * currencyId: -1 ：综合本位币:所有科目（不管有没有外币），只要有金额（期初或者凭证）
     * currencyId: -2 ：人民币，不勾选外币核算的
     * @return
     */
    @IgnoresLogin
    @GetMapping("/generalLedgerByParam1")
    public JsonResult generalLedgerByParam(String startTime, String endTime, String startSubject, String endSubject, Integer startLevel, Integer endLevel, boolean isOpen, boolean showNumPrice,Integer currencyId) {
        List<Map<String, Object>> mapsList = new ArrayList<>();
        List<Map<String, Object>> mapsSet = new ArrayList<>();
        List<String> dateList = DateUtil.getMonthBetweenDate(startTime, endTime);
        //当前查询账套
        AccountSets accountSets = accountSetsMapper.selectById(this.accountSetsId);

        List<Subject> subjectList = service.accountBookListByParam(startTime,endTime ,startSubject, endSubject, startLevel,endLevel,this.accountSetsId,isOpen,showNumPrice,currencyId);

        if (subjectList.size() == 0){
            return JsonResult.successful();
        }
        for (int i = 0; i < dateList.size(); i++) {
            String sTime = dateList.get(i)+"-01";
            String eTime = dateList.get(i)+ "-" + DateUtil.getDayOfMonth(DateUtil.parseDate(dateList.get(i)+"-01"));
            List<Map<String, Object>> data = this.voucherService.accountGeneralLedgerByParam(accountSets, sTime, eTime, startSubject, endSubject, startLevel, endLevel, isOpen, showNumPrice,currencyId,subjectList);
            for (Map<String, Object> datum : data) {
                mapsList.add(datum);
                mapsSet.add(datum);
            }
        }
        List<Map<String, Object>> resulMaps = new ArrayList<>();
        for(int i = 0; i < mapsList.size(); i++){
            Subject listSub = (Subject) mapsList.get(i).get("subject");
            for(int j = 0; j < mapsSet.size(); j++){
                Subject setSub = (Subject) mapsSet.get(j).get("subject");
                if(listSub.getCode().equals(setSub.getCode())){
                    resulMaps.add(mapsSet.get(j));
                }
            }
        }
        Iterator<Map<String, Object>> iterator = resulMaps.iterator();
        while (iterator.hasNext()) {
            Map<String, Object> item = iterator.next();
            if (resulMaps.indexOf(item) != resulMaps.lastIndexOf(item)) {
                iterator.remove();
            }
        }

        resulMaps.forEach(System.out::println);
        //排序
        List<Map<String, Object>> orderByMaps = new ArrayList<>();
        List<String> codeList = new ArrayList<>();
        for (Map<String, Object> resulMap : resulMaps) {
            Subject subject = (Subject) resulMap.get("subject");
            codeList.add(subject.getCode());
        }
        List<String> collect = codeList.stream().distinct().collect(Collectors.toList());
        Collections.sort(collect);
        for (String code : collect) {
            for (Map<String, Object> resulMap : resulMaps) {
                Subject subject = (Subject) resulMap.get("subject");
                if (subject.getCode().equals(code)){
                    List<VoucherDetailVo> summary = (List<VoucherDetailVo>) resulMap.get("summary");
                    Map<String, Object> item = new HashMap<>(2);
                    item.put("subject", subject);
                    item.put("summary", summary);
                    orderByMaps.add(item);
                }
            }
        }
        return JsonResult.successful(orderByMaps);
    }


    /**
     * 从总账这边 查看 某个科目的明细账
     *
     * @param subjectId
     * @param accountDate
     * @param subjectCode
     * @return
     */
    @IgnoresLogin
    @GetMapping("/findDetailsByParam")
    @TokenValid
    public JsonResult accountBookfindDetails(Integer accSetsId, Integer subjectId, Date accountDate, String subjectCode, Boolean showNumPrice) {
        List data = this.voucherService.accountBookDetails(accSetsId, subjectId, accountDate, subjectCode, showNumPrice);
        return JsonResult.successful(data);
    }

    /**
     * 辅助明细账
     *
     * @param auxiliaryId
     * @param accountDate
     * @param auxiliaryItemId
     * @return
     */
    @IgnoresLogin
    @GetMapping("auxiliaryDetails")
    public JsonResult auxiliaryDetails(Integer auxiliaryId, Date accountDate, Integer auxiliaryItemId, Boolean showNumPrice) {
        List data = this.voucherService.auxiliaryDetails(this.accountSetsId, auxiliaryId, accountDate, auxiliaryItemId, showNumPrice);
        return JsonResult.successful(data);
    }


    /**
     * 核算项目明细账 - 动态-重构
     *
     * @param auxiliaryId
     * @param
     * @param auxiliaryItemId
     * @return
     */
    @IgnoresLogin
    @GetMapping("auxiliaryDetailsByParam")
    public JsonResult auxiliaryDetailsByParam3(
            Integer accountingCategoryId,
            Integer accountingCategoryDetailsId,
            String sTime,
            String eTime,
            String subjectCode,
            String auxiliaryTitle,
            Boolean showNumPrice) {

        List<VoucherDetailVo>  voucherDetailVoList = this.voucherService.auxiliaryDetailsByParam3(this.accountSetsId,accountingCategoryId,accountingCategoryDetailsId,sTime,eTime,subjectCode,auxiliaryTitle,showNumPrice);
        return JsonResult.successful(voucherDetailVoList);
    }

    /**
     * 核算项目明细账 - 动态-重构前
     *
     * @param auxiliaryId
     * @param
     * @param auxiliaryItemId
     * @return
     */
    @IgnoresLogin
    @GetMapping("auxiliaryDetailsByParam3")
    public JsonResult auxiliaryDetailsByParam2(
            Integer auxiliaryId,
            String sTime,
            String eTime,
            String subjectCode,
            Integer auxiliaryItemId,
            String auxiliaryTitle,
            Boolean showNumPrice) {

        List<VoucherDetailVo> data = null;
        List<VoucherDetailVo> resultData = new ArrayList();
        List<String> dateList = DateUtil.getMonthBetweenDate(sTime, eTime);


        for (String s : dateList) {
            String sti = s+"-01";
            String eti = s+ "-" + DateUtil.getDayOfMonth(DateUtil.parseDate(s+"-01"));
            Date st = DateUtil.parseDate(sti);
            Date et = DateUtil.parseDate(eti);
            data = this.voucherService.auxiliaryDetailsByParam2(this.accountSetsId, auxiliaryId, st, et, subjectCode, auxiliaryItemId, showNumPrice);
            data.forEach(ob->{
                resultData.add(ob);
            });
        }


        //重新计算本年累计（需要加上期初）
        AccountSets accountSets = accountSetsMapper.selectById(accountSetsId);

        if (DateUtil.getYear(accountSets.getEnableDate()) == DateUtil.getYear(new Date())){
            //说明账套启动年月是本年，需要加上期初的金额

        }
        List<VoucherDetails> detailsMapperAuxiliary = voucherDetailsMapper.findAuxiliary(resultData, auxiliaryTitle);
        for (VoucherDetails voucherDetails : detailsMapperAuxiliary) {
            System.out.println(voucherDetails);
        }
        System.out.println("============");
        for (VoucherDetailVo resultDatum : resultData) {
            System.out.println(resultDatum);
        }
        resultData.forEach(vo->{

        });
        return JsonResult.successful(resultData);
    }









    private List<Date> getDate(String stime, String etime){
        Date sTimeDate = new Date();
        Date eTimeDate = new Date();

        try{
            sTimeDate = new SimpleDateFormat("yyyy-MM-dd").parse(stime);
            eTimeDate = new SimpleDateFormat("yyyy-MM-dd").parse(etime);

            int sM = DateUtil.getMonth(sTimeDate);
            int eM = DateUtil.getMonth(eTimeDate);

            int sY = DateUtil.getYear(sTimeDate);
            int eY = DateUtil.getYear(eTimeDate);

            int sD = DateUtil.getDay(sTimeDate);
            int eD = DateUtil.getDay(eTimeDate);

            List<Date> timeList = new ArrayList<>();

            LocalDate startDate = LocalDate.of(sY, sM, sD);
            LocalDate endDate = LocalDate.of(eY, eM, eD);

            List<LocalDate> dates = getDatesBetween(startDate, endDate);
            Set<Date> datesN = new HashSet<>();

            if (dates.size() == 1){
                timeList.add(eTimeDate);
                return timeList;
            }else if(dates.size() > 1 && !formate(startDate).equals(formate(endDate))){
                //筛除 起始 结束时间
                //并格式化 时间 yyyy-mm
                for(LocalDate d:dates){
                    if(formate(d).equals(formate(startDate)) ||formate(d).equals(formate(endDate))){

                    }else {
                        datesN.add(new SimpleDateFormat("yyyy-MM").parse(formate(d)));
                    }
                };
                timeList.add(sTimeDate);
                for(Date d : datesN){
                    timeList.add(new SimpleDateFormat("yyyy-MM-dd").parse(
                            DateUtil.getYear(d)+"-"+DateUtil.getMonth(d)+"-"+DateUtil.getDayOfMonth(d))
                    );
                }
                timeList.add(eTimeDate);
                return timeList;
            }else if(formate(startDate).equals(formate(endDate))){
                timeList.add(sTimeDate);
                timeList.add(eTimeDate);
                return timeList;
            }

        }catch (Exception e){
            System.out.println("日期转换错误");
        }
        return null;
    }

    public static String formate(LocalDate localDate){
        DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("yyyy-MM");
        String s = timeFormat.format(localDate);
       return s;
    }


    public static List<LocalDate> getDatesBetween(LocalDate startDate, LocalDate endDate) {
        List<LocalDate> dates = new ArrayList<>();
        long numOfDaysBetween = ChronoUnit.DAYS.between(startDate, endDate);
        for (int i = 0; i <= numOfDaysBetween; i++) {
            LocalDate date = startDate.plusDays(i);
            dates.add(date);
        }
        return dates;
    }


    public static int getDaysOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }


    /**
     * 当期核算项目列表
     *
     * @param auxiliaryId
     * @return
     */
    @GetMapping("auxiliaryList")
    public JsonResult auxiliaryList(Integer auxiliaryId) {
        List data = this.voucherService.auxiliaryList(this.accountSetsId, auxiliaryId);
        return JsonResult.successful(data);
    }

    /**
     * 核算项目余额
     *
     * @param accountDate
     * @param auxiliaryId
     * @return
     */
    @IgnoresLogin
    @GetMapping("auxiliaryBalance")
    public JsonResult auxiliaryBalance(Date accountDate, Integer auxiliaryId, Boolean showNumPrice) {
        List data = this.voucherService.auxiliaryBalance(this.accountSetsId, auxiliaryId, accountDate, showNumPrice);
        return JsonResult.successful(data);
    }


    /**
     * 核算项目余额-动态查询
     *
     * @param
     * @param auxiliaryId
     * @return
     */
    @IgnoresLogin
    @GetMapping("/auxiliaryBalanceByParam")
    public JsonResult auxiliaryBalanceByParam(
            String sTime,
            String eTime,
            String subjectCode,
            Integer auxiliaryId,
            String detailsAuxiliaryId,
            boolean showNumPrice) {


        String subjectCode1 = "";
        String subjectCode2 = "";
        List<String> subList = new ArrayList<>();
        if (BaseUtil.checkValueIsNull(subjectCode).contains("-")) {
            String[] sry = subjectCode.split("-");
            subjectCode1 = sry[0];
            subjectCode2 = sry[1];
        } else if (BaseUtil.checkValueIsNull(subjectCode).contains(",")) {
            String[] sry = subjectCode.split(",");
            subList.add(sry[0]);
            subList.add(sry[1]);
        } else {
            if (!BaseUtil.checkValueIsNull(subjectCode).equals("")) {
                subList.add(subjectCode);
            }
        }
        List data = this.voucherService.auxiliaryBalanceByParam(this.accountSetsId, sTime, eTime, subjectCode1, subjectCode2, auxiliaryId, detailsAuxiliaryId, subList, showNumPrice);
        //等于1就说明只有一个合计，所以不用返回
        if (data.size() == 1){
            List<BalanceVo> list = new ArrayList<>();
            return JsonResult.successful( list);
        }
        return JsonResult.successful(data);
    }

}

